import { BrowserWindow, ipcMain, screen } from 'electron'
import { WindowTypes } from '@globalTypes/global'
import { StorageTool } from './StorageTool'

export class WindowBoundTool {
  // 窗口实例
  private win: BrowserWindow

  // 计时器，用于延时
  private movingInterval: ReturnType<typeof setInterval> | null = null

  // 窗口id，不能重复
  private windowKey: string

  private storageTool: StorageTool

  // 窗口最终位置
  private winBound: WindowTypes.WindowBound = {
    x: 0,
    y: 0,
    width: 0,
    height: 0
  }

  constructor(win: BrowserWindow, windowKey: string, initBound: WindowTypes.WindowBound, izCenter = false) {
    this.win = win
    this.windowKey = windowKey
    this.storageTool = new StorageTool('position')
    this.initWindowBound(initBound, izCenter)
  }

  // 初始化窗口移动事件监听器
  initWinMoveEventListener() {
    // 监听窗口移动事件
    ipcMain.on('window-move-open', (event, canMoving) => {
      // 窗口开始移动位置
      let winStartPosition = {
        x: 0,
        y: 0,
        width: this.winBound.width,
        height: this.winBound.height
      }
      // 鼠标开始位置
      let mouseStartPosition = {
        x: 0,
        y: 0
      }
      // 判断一下是不是当前窗口，以防其他窗口也可以按住拖动
      const eventWin = BrowserWindow.fromWebContents(event.sender)!
      if (eventWin !== this.win) return
      if (canMoving) {
        // 开始移动
        // 读取原位置和窗口大小
        const bounds = this.win.getBounds()
        winStartPosition = {
          x: bounds.x,
          y: bounds.y,
          width: bounds.width,
          height: bounds.height
        }
        // 获取鼠标开始位置
        mouseStartPosition = screen.getCursorScreenPoint()
        // 鼠标位置和窗口位置的差值
        const gapX = mouseStartPosition.x - winStartPosition.x
        const gapY = mouseStartPosition.y - winStartPosition.y
        // 清除延时
        if (this.movingInterval) {
          clearInterval(this.movingInterval)
        }
        // 新建延时
        this.movingInterval = setInterval(() => {
          const cursorPosition = screen.getCursorScreenPoint()
          const moveX = cursorPosition.x - gapX
          const moveY = cursorPosition.y - gapY
          if (moveX === winStartPosition.x && moveY === winStartPosition.y) return // 鼠标没有移动，不执行任何操作
          // 如果windows系统设置的缩放比例不是100%时，只修改位置，会导致窗口大小发生变化，因此需要一并设置窗口大小，缺点是，这样会导致拖动时窗口抖动，暂时没有更好的解决办法
          this.winBound.x = moveX
          this.winBound.y = moveY
          this.win.setBounds(this.winBound, true)
        }, 20)
      } else {
        // 清除延时，结束移动
        if (this.movingInterval !== null) {
          clearInterval(this.movingInterval)
        }
        this.movingInterval = null
        // 将窗口最终的位置保存
        this.setWindowBoundStorage()
      }
    })
  }

  // 初始化窗口位置
  initWindowBound(initBound: WindowTypes.WindowBound, izCenter: boolean = false) {
    // 从本地存储中获取窗口边界位置
    const localPos = this.getWindowBoundStorage()
    // 获取屏幕主显示器的尺寸
    const { width, height } = screen.getPrimaryDisplay().workAreaSize
    // 如果本地存储中有窗口边界位置
    if(localPos) {
      // 判断如果窗口边界位置不在屏幕范围内，则将窗口边界位置设置为屏幕范围内
      let x = localPos.x
      let y = localPos.y
      if(localPos.x !== 0 && localPos.y !== 0) {
        if(localPos.x > width || localPos.x <= 0 || localPos.y > height || localPos.y <= 0) {
          x = width - localPos.width - 100
          y = height - localPos.height - 40
        }
      }
      // 将本地存储中的窗口边界位置赋值给当前窗口边界
      this.winBound = {
        ...localPos,
        x,
        y
      }
    }else{
      if(izCenter) {
        return
      }
      this.winBound = initBound
      // 设置窗口的x坐标为屏幕宽度减去窗口宽度再减去100
      if(initBound.x <= 0) {
        this.winBound.x = width - this.winBound.width - 100
      }
      // 设置窗口的y坐标为屏幕高度减去窗口高度再减去40
      if(initBound.y <= 0) {
        this.winBound.y = height - this.winBound.height - 40
      }
    }
    // 设置窗口的边界并应用
    this.win.setBounds(this.winBound, true)
  }

  // 获取持久化的窗口位置
  getWindowBoundStorage():WindowTypes.WindowBound | null {
    const str = this.storageTool.getStorageStr(this.windowKey)
    if (str != null && str != 'undefined') {
      return JSON.parse(str) as WindowTypes.WindowBound
    }
    return null
  }

  // 持久化窗口位置
  setWindowBoundStorage() {
    this.storageTool.setStorageStr(this.windowKey, JSON.stringify(this.winBound))
  }
}
